﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ShevaEngine.Core.Modules.Scenes;
using System.Collections.ObjectModel;
using ShevaEngine.Core.GameLogic.Messages;

namespace ShevaEngine.Core.GameLogic
{
    /// <summary>
    /// Main Game Core.
    /// </summary>
    public class GameCore
    {        
        /// <summary>Game core objects.</summary>
        private Dictionary<Guid, IGameCoreObject> GameCoreObjects;
        /// <summary>Entities.</summary>
        public ObservableCollection<IGameCoreObject> Entities { get; private set; }
        /// <summary>Visible entities.</summary>
        public ObservableCollection<IVisibleGameCoreObject> VisibleEntities { get; private set; }
        /// <summary>Hearable entities.</summary>
        public ObservableCollection<IHearableGameCoreObject> HearableEntities { get; private set; }

        /// <summary>
        /// Constructor.
        /// </summary>
        public GameCore()
        {
            this.GameCoreObjects = new Dictionary<Guid, IGameCoreObject>();
            this.Entities = new ObservableCollection<IGameCoreObject>();
            this.HearableEntities = new ObservableCollection<IHearableGameCoreObject>();
            this.VisibleEntities = new ObservableCollection<IVisibleGameCoreObject>();
        }

        /// <summary>
        /// Method registers game core object.
        /// </summary>
        /// <param name="gCoreObject"></param>
        public void RegisterGameCoreObject(IGameCoreObject gCoreObject)
        {
            this.GameCoreObjects.Add(gCoreObject.Id, gCoreObject);

            if (gCoreObject is IGameCoreObject)
                this.Entities.Add(gCoreObject as IGameCoreObject);

            if (gCoreObject is IVisibleGameCoreObject)
                this.VisibleEntities.Add(gCoreObject as IVisibleGameCoreObject);

            if (gCoreObject is IHearableGameCoreObject)
                this.HearableEntities.Add(gCoreObject as IHearableGameCoreObject);
        }

        /// <summary>
        /// Method unregister game core object.
        /// </summary>
        /// <param name="gCoreObject"></param>
        public void UnregisterGameCoreObject(IGameCoreObject gCoreObject)
        {
            if (this.GameCoreObjects.ContainsKey(gCoreObject.Id))
                this.GameCoreObjects.Remove(gCoreObject.Id);

            if (gCoreObject is IGameCoreObject && this.Entities.Contains(gCoreObject as IGameCoreObject))
                this.Entities.Add(gCoreObject as IGameCoreObject);

            if (gCoreObject is IVisibleGameCoreObject && this.VisibleEntities.Contains(gCoreObject as IVisibleGameCoreObject))
                this.VisibleEntities.Add(gCoreObject as IVisibleGameCoreObject);

            if (gCoreObject is IHearableGameCoreObject && this.HearableEntities.Contains(gCoreObject as IHearableGameCoreObject))
                this.HearableEntities.Add(gCoreObject as IHearableGameCoreObject);
        }

        /// <summary>
        /// Method gets scene object from Guid.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public SceneObject GetSceneObjectFromGuid(Guid id)
        {
            if (this.GameCoreObjects.ContainsKey(id))
                return GameCoreObjects[id] as SceneObject;

            return null;
        }

        /// <summary>
        /// Method processes Game Core Object message.
        /// </summary>
        /// <param name="message"></param>
        public void ProcessMessage(GameCoreMessage message)
        {
            if (message is InteractivityMessage)
                if (this.GameCoreObjects.ContainsKey((message as InteractivityMessage).Receiver))
                    this.GameCoreObjects[(message as InteractivityMessage).Receiver].ProcessMessage(message);
        }
    }
}
